//
//  ViewController.m
//  RSA-OAEPWithSHA256AndMGF1Padding
//
//  Created by 张程iOS on 2022/1/17.
//

#import "ViewController.h"
#import <openssl/pem.h>
#import <openssl/RSAFixed.h>


@interface ViewController ()

@end

@implementation ViewController
/**
 参考简书：https://www.jianshu.com/p/f488f8631ac8
 这里主要： OpenSSL/opensslincludes/openssl/RSAFixed.h
 
 主要解决的问题： iOS RSA/ECB/OAEPWithSHA-256AndMGF1Padding加密
 在给定公钥的模(mod)和幂(Exp)情况下，进行加密
 
 
 可能存在的问题：
 1.这里使用方法交换，所以需要引入部分头文件，有些.h可删减。
 2.头文件找不到这里低级问题：search Paths问题。
*/

- (void)viewDidLoad {
    [super viewDidLoad];
}


//根据公钥模和幂进行加密
-(NSData *)getRSAWithOAEPWithSHA256AndMGF1Padding:(NSString *)input mod:(NSString *)mod exp:(NSString *)exp{
    if(mod.length == 0 || exp.length == 0 || input.length == 0 ){
        return nil;
    }else{
        RSA * rsa_pub = RSA_new();
        const char *N=[mod UTF8String] ;
        const char *E=[exp UTF8String];
        if (!BN_hex2bn(&rsa_pub->n, N)) {
            return nil;
        }
        if (!BN_hex2bn(&rsa_pub->e, E)) {
            return nil;
        }

//        return rsa_pub;
        if(rsa_pub!=nil){
            NSData *plainData = [input dataUsingEncoding:NSUTF8StringEncoding];
            int paddingSize = 0;
            int publicRSALength = RSA_size(rsa_pub);
            double totalLength = [plainData length];
            int blockSize = publicRSALength - paddingSize;
            int blockCount = ceil(totalLength / blockSize);
            size_t publicEncryptSize = publicRSALength;
            NSMutableData *encryptDate = [NSMutableData data];
            for (int i = 0; i < blockCount; i++) {
                NSUInteger loc = i * blockSize;
                int dataSegmentRealSize = MIN(blockSize, totalLength - loc);
                NSData *dataSegment = [plainData subdataWithRange:NSMakeRange(loc, dataSegmentRealSize)];
                char *publicEncrypt = malloc(publicRSALength);
                memset(publicEncrypt, 0, publicRSALength);
                const unsigned char *str = [dataSegment bytes];
                int r = RSA_public_encrypt_sha256(dataSegmentRealSize,str,(unsigned char*)publicEncrypt,rsa_pub,RSA_PKCS1_OAEP_PADDING);
                if (r < 0) {
                    free(publicEncrypt);
                    return nil;
                }
                NSData *encryptData = [[NSData alloc] initWithBytes:publicEncrypt length:publicEncryptSize];
                [encryptDate appendData:encryptData];

                free(publicEncrypt);
            }
            return encryptDate;
        }else{
            return nil;
        }
    }
}




@end
